import { Env, Native, timeout, Toast } from '@/modules';
import { DeviceEventEmitter, Platform } from 'react-native';
import { Storage } from '@/modules';
import { HttpClient, Api as OpenApi } from './openApi';

const { version } = require('../../app.json');
const errorCode = require('../../errorCode.json');
const timeOffset = new Date().getTimezoneOffset() / -60;

/**
 * 固定的公共请求头
 */
export const publicHeader = {
  Accept: 'application/json;charset=utf-8',
  saas_id: 'duom',
  device_type: Platform.OS,
  language: 'en',
  TIME_ZONE: timeOffset.toString(),
  'content-type': 'application/json; charset=UTF-8',
  version: version,
};

/**
 * API响应接口
 */
export interface ApiResponse<T = any> {
  success: boolean;
  data?: T;
  message?: string;
  code?: number;
  obj?: T;
}

/**
 * 请求选项接口
 */
export interface RequestOptions {
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
  headers?: Record<string, string>;
  body?: string | FormData;
  timeout?: number;
  disableToast?: boolean;
  disableLoginExpired?: boolean;
  urlEncode?: boolean;
  headerEx?: Record<string, string>;
}

/**
 * 获取请求头
 */
async function getHeader(opt: RequestOptions = {}) {
  const headers = {
    ...publicHeader,
    device_id: await Native.getDeviceId(),
    'content-type': opt.urlEncode
      ? 'application/x-www-form-urlencoded'
      : 'application/json; charset=UTF-8',
  };

  const loginInfo = Storage.getLoginInfo();
  if (loginInfo) {
    Object.assign(headers, {
      jwt_token: loginInfo.jwtKey,
      customer_id: loginInfo.id,
      Authorization: loginInfo.jwtKey,
    });
  }

  if (opt.headerEx) {
    Object.assign(headers, opt.headerEx);
  }

  return headers;
}

/**
 * 核心请求函数
 */
async function makeRequest<T>(config: {
  url: string;
  method: string;
  body: string;
  opt: RequestOptions;
}): Promise<T> {
  const { url, method, body, opt } = config;
  const headers = await getHeader(opt);

  const init: RequestInit = { method, headers };
  if (body) {
    Object.assign(init, { body });
  }

  const time = opt.timeout || 20000;
  const res = (await Promise.race([fetch(url, init), timeout(time, url)]).catch(
    (err: any) => {
      if (!opt.disableToast) {
        Toast.toggle('Please check your internet connection and try again.');
      }
      throw new Error(err);
    }
  )) as Response;

  return await onFinish<T>(url, body, res, opt);
}

/**
 * api请求完成后的处理
 */
async function onFinish<T>(
  url: string,
  body: string,
  response: Response,
  opt: RequestOptions
): Promise<T> {
  await handleCaptchaResponse(url, body, response, opt);

  const text = await response.text();
  const res = JSON.parse(text);

  if (
    response.status !== 200 ||
    res.success === false ||
    res?.result?.ok === false
  ) {
    handleAnalytics(url, body, text, response.status + '');
    handleLoginExpired(res, opt, url, body);
    throw new Error(JSON.stringify(res));
  }

  return (res.obj || res.data || res) as T;
}

/**
 * 处理验证码响应
 */
async function handleCaptchaResponse<T>(
  url: string,
  body: string,
  response: Response,
  opt: RequestOptions
) {
  // 验证码处理逻辑可以在这里添加
}

/**
 * 处理登录过期
 */
function handleLoginExpired(
  res: any,
  opt: RequestOptions,
  url: string,
  body: string
) {
  const loginExpired =
    res.msgKey === 'customer.login.required' ||
    (res.result?.statusCode === 400 && res.result?.code === 3);

  if (!opt.disableLoginExpired && loginExpired) {
    const loginInfo = Storage.getLoginInfo();
    // 处理登录过期逻辑
  } else if (res.code === '200000') {
    // 注册登录相关的接口登录失败 模糊提示
  } else if (!opt.disableToast) {
    const codeStr = errorCode[res.code];
    const errorCodeMes = codeStr ? codeStr : 'Oops! Something went wrong.';
    Toast.toggle(errorCodeMes);
  }
}

/**
 * 处理分析数据
 */
function handleAnalytics(
  url: string,
  body: string,
  text: string,
  status?: string
) {
  if (!url) {
    return;
  }
  // 分析数据处理逻辑
}

/**
 * URL编码函数
 */
export function urlEncode(map: Record<string, any>): string {
  const pairs: string[] = [];
  for (const key in map) {
    if (map.hasOwnProperty(key)) {
      const value = map[key];
      if (value !== undefined && value !== null) {
        pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
      }
    }
  }
  return pairs.join('&');
}

/**
 * 创建OpenAPI客户端实例
 */
async function createOpenApiClient() {
  const domain = await Env.wget();
  return new OpenApi({
    baseUrl: domain.api,
    customFetch: async (url, options = {}) => {
      // 添加自定义请求头
      const loginInfo = Storage.getLoginInfo();
      if (loginInfo) {
        options.headers = {
          ...options.headers,
          jwt_token: loginInfo.jwtKey,
          customer_id: loginInfo.id,
          Authorization: loginInfo.jwtKey,
        };
      }

      // 添加设备信息
      const deviceId = await Native.getDeviceId();
      options.headers = {
        ...options.headers,
        device_id: deviceId,
        ...publicHeader,
      };

      return fetch(url, options);
    },
  });
}

/**
 * 通用API类
 */
export namespace Api {
  /**
   * GET请求
   */
  export async function get<T>(
    path: string,
    param: Record<string, any> = {},
    opt: RequestOptions = {}
  ): Promise<T> {
    const domain = await Env.wget();
    const url = `${domain.api}${path}?${urlEncode(param)}`;
    return await makeRequest<T>({ url, method: 'GET', body: '', opt });
  }

  /**
   * POST请求
   */
  export async function post<T>(
    path: string,
    param: Record<string, any> = {},
    opt: RequestOptions = {}
  ): Promise<T> {
    const domain = await Env.wget();
    const url = `${domain.api}${path}`;
    const body = opt.urlEncode ? urlEncode(param) : JSON.stringify(param);
    return await makeRequest<T>({ url, method: 'POST', body, opt });
  }

  /**
   * PUT请求
   */
  export async function put<T>(
    path: string,
    param: Record<string, any> = {},
    opt: RequestOptions = {}
  ): Promise<T> {
    const domain = await Env.wget();
    const url = `${domain.api}${path}`;
    const body = opt.urlEncode ? urlEncode(param) : JSON.stringify(param);
    return await makeRequest<T>({ url, method: 'PUT', body, opt });
  }

  /**
   * DELETE请求
   */
  export async function delete$<T>(
    path: string,
    param: Record<string, any> = {},
    opt: RequestOptions = {}
  ): Promise<T> {
    const domain = await Env.wget();
    const url = `${domain.api}${path}?${urlEncode(param)}`;
    return await makeRequest<T>({ url, method: 'DELETE', body: '', opt });
  }

  /**
   * 通用请求方法
   */
  export async function request<T>(
    url: string,
    method: string = 'GET',
    headers?: Record<string, string>,
    param: Record<string, any> = {},
    opt: RequestOptions = {}
  ): Promise<T> {
    const domain = await Env.wget();
    const fullUrl = url.startsWith('http') ? url : `${domain.api}${url}`;

    const requestOpt: RequestOptions = {
      ...opt,
      headerEx: headers,
    };

    if (method === 'GET' || method === 'DELETE') {
      const urlWithParams = `${fullUrl}?${urlEncode(param)}`;
      return await makeRequest<T>({
        url: urlWithParams,
        method,
        body: '',
        opt: requestOpt,
      });
    } else {
      const body = opt.urlEncode ? urlEncode(param) : JSON.stringify(param);
      return await makeRequest<T>({
        url: fullUrl,
        method,
        body,
        opt: requestOpt,
      });
    }
  }

  /**
   * 便捷方法 - 兼容旧版apiRequest
   */
  export async function apiRequest<T = any>(
    endpoint: string,
    options: RequestOptions = {}
  ): Promise<ApiResponse<T>> {
    try {
      const domain = await Env.wget();
      const url = `${domain.api}${endpoint}`;

      const result = await makeRequest<T>({
        url,
        method: options.method || 'GET',
        body: options.body || '',
        opt: options,
      });

      return {
        success: true,
        data: result,
      };
    } catch (error) {
      console.error('API request failed:', error);
      return {
        success: false,
        message: '网络错误，请稍后重试',
        code: 500,
      };
    }
  }

  /**
   * 便捷GET方法
   */
  export async function apiGet<T = any>(
    endpoint: string
  ): Promise<ApiResponse<T>> {
    return apiRequest<T>(endpoint, { method: 'GET' });
  }

  /**
   * 便捷POST方法
   */
  export async function apiPost<T = any>(
    endpoint: string,
    data?: any
  ): Promise<ApiResponse<T>> {
    return apiRequest<T>(endpoint, {
      method: 'POST',
      body: data ? JSON.stringify(data) : undefined,
    });
  }

  /**
   * 便捷PUT方法
   */
  export async function apiPut<T = any>(
    endpoint: string,
    data?: any
  ): Promise<ApiResponse<T>> {
    return apiRequest<T>(endpoint, {
      method: 'PUT',
      body: data ? JSON.stringify(data) : undefined,
    });
  }

  /**
   * 便捷DELETE方法
   */
  export async function apiDelete<T = any>(
    endpoint: string
  ): Promise<ApiResponse<T>> {
    return apiRequest<T>(endpoint, { method: 'DELETE' });
  }

  /**
   * OpenAPI客户端实例
   */
  export const openApi = createOpenApiClient();

  /**
   * 使用OpenAPI的便捷方法
   */
  export const openApiClient = {
    /**
     * 获取用户信息
     */
    async getPassport() {
      try {
        const response = await Api.openApi.v1.passport.get();
        return response.data;
      } catch (error) {
        console.error('获取用户信息失败:', error);
        throw error;
      }
    },

    /**
     * 获取任务列表
     */
    async getTaskList() {
      try {
        const response = await Api.openApi.v1.task.list.get();
        return response.data;
      } catch (error) {
        console.error('获取任务列表失败:', error);
        throw error;
      }
    },

    /**
     * 获取通知列表
     */
    async getNoticeList() {
      try {
        const response = await Api.openApi.v1.notice.list.get();
        return response.data;
      } catch (error) {
        console.error('获取通知列表失败:', error);
        throw error;
      }
    },

    /**
     * 获取新闻列表
     */
    async getNewsList() {
      try {
        const response = await Api.openApi.v1.news.list.get();
        return response.data;
      } catch (error) {
        console.error('获取新闻列表失败:', error);
        throw error;
      }
    },

    /**
     * 获取邀请信息
     */
    async getInviteInfo() {
      try {
        const response = await Api.openApi.v1.invite.info.get();
        return response.data;
      } catch (error) {
        console.error('获取邀请信息失败:', error);
        throw error;
      }
    },

    /**
     * 绑定邀请码
     */
    async bindInvite(inviteCode: string) {
      try {
        const response = await Api.openApi.v1.invite.bind.post({
          inviteCode,
        });
        return response.data;
      } catch (error) {
        console.error('绑定邀请码失败:', error);
        throw error;
      }
    },

    /**
     * 第三方授权
     */
    async thirdAuthorize(platform: string, code: string) {
      try {
        const response = await Api.openApi.v1.third.authorize.post({
          platform,
          code,
        });
        return response.data;
      } catch (error) {
        console.error('第三方授权失败:', error);
        throw error;
      }
    },

    /**
     * 获取第三方绑定信息
     */
    async getThirdBindings() {
      try {
        const response = await Api.openApi.v1.third.bindings.get();
        return response.data;
      } catch (error) {
        console.error('获取第三方绑定信息失败:', error);
        throw error;
      }
    },

    /**
     * 获取挑战码
     */
    async getChallenge() {
      try {
        const response = await Api.openApi.v1.challenge.get();
        return response.data;
      } catch (error) {
        console.error('获取挑战码失败:', error);
        throw error;
      }
    },

    /**
     * 登录
     */
    async login(walletAddress: string, signature: string, code?: string) {
      try {
        const response = await Api.openApi.v1.login.post({
          walletAddress,
          signature,
          code,
        });
        return response.data;
      } catch (error) {
        console.error('登录失败:', error);
        throw error;
      }
    },

    /**
     * 登出
     */
    async logout() {
      try {
        const response = await Api.openApi.v1.logout.post();
        return response.data;
      } catch (error) {
        console.error('登出失败:', error);
        throw error;
      }
    },
  };
}
